﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using WebCommit.Common.Helpers;
using WebCommit.Common.Entitys;
using NHibernate.Criterion;
using System.Security.Cryptography;
using System.Net.Mail;
using WebCommit.Common.Constants;
using WebCommit.Common;
using System.Net;

namespace WebCommit.BizL.User
{
	public class UserBiz
	{
		#region singleton
		public static UserBiz CurrentInstance
		{
			get {
				if (_Instance == null)
					_Instance = new UserBiz();
				return _Instance;
			}
		}

		private static UserBiz _Instance = null;

		private UserBiz()
		{ }
		#endregion

		private ISession GetSession()
		{ 
			ISession session = NHibernateHelper.GetSession(WebCommit.Common.Constants.Config.HBSessionKey_WebCommit);
			return session;
		}

		public bool IsUserNameExists(string userName)
		{
			ISession session = GetSession();
			return session.CreateCriteria<UserEntity>().Add(Expression.Eq("UserName", userName)).List().Count>0;
		}

		public bool IsNickNameExists(string nickName)
		{
			ISession session = GetSession();
			return session.CreateCriteria<UserEntity>().Add(Expression.Eq("NickName", nickName)).List().Count > 0;
		}

		public void RegUser(UserEntity user)
		{ 
			ISession session = GetSession();
			ITransaction tran = session.Transaction;
			tran.Begin();
			user.UserStatus = Common.Enums.UserStatus.Pending;
			user.Password = HashPassword(user.Password);
			session.Save("UserEntity",user);
			RegValidateEntity regVal = AddValidateEntity(user.Id, session);
			tran.Commit();
			SendValidateMail(user, regVal);
		}

		private RegValidateEntity AddValidateEntity(string userId, ISession sess)
		{
			sess.Delete("from RegValidateEntity where UserID='" + userId + "'");
			RegValidateEntity regVal = new RegValidateEntity() { UserID = userId, ValidateCode = Guid.NewGuid().ToString() };
			sess.Save(regVal);
			return regVal;
		}

		private void SendValidateMail(UserEntity user,RegValidateEntity regVal)
		{
			MailMessage mail = new MailMessage();
			string valUrl = Utility.GetCurrentSiteUrl() + "UserMgr/Validate/" + regVal.Id + "?UserID=" + regVal.UserID + "&ValidateCode=" + regVal.ValidateCode;
			mail.From = new MailAddress(Utility.GetAppCfg<string>(Config.ValidateMailFrom), Utility.GetAppCfg("ValidateMailFromDisplayName"));
			mail.To.Add(new MailAddress(user.Email, user.NickName));
			mail.Subject = Resource.GetResource("Validate_MailSubject");
			mail.IsBodyHtml = true;
			mail.Body = string.Format(Resource.GetResource("Validate_MailBody"), user.NickName, valUrl, valUrl);
			SmtpClient smtp = new SmtpClient(Utility.GetAppCfg<string>(Config.SmtpHost),Utility.GetAppCfg<int>(Config.SmtpPort));
			smtp.Credentials = new NetworkCredential(Utility.GetAppCfg(Config.SmtpUserName), Utility.GetAppCfg(Config.SmtpPwd));
			
			smtp.SendAsync(mail,null);
		}

		public void UpdateUser(UserEntity user)
		{ 
		
		}



		public UserEntity Login(string userName, string password)
		{
			ISession session = GetSession();
			UserEntity user = session.CreateCriteria<UserEntity>()
				.Add(Expression.Eq("UserName", userName))
				.Add(Expression.Eq("Password", HashPassword(password)))
				.UniqueResult<UserEntity>();
			//if (user != null)
			//    user.Password = "";
			return user;
		}

		private string HashPassword(string password)
		{
			byte[] data = Encoding.GetEncoding("UTF-8").GetBytes(password + WebCommit.Common.Constants.SystemConst.PasswordSalt);
			MD5 md5 = new MD5CryptoServiceProvider();
			byte[] OutBytes = md5.ComputeHash(data);

			string OutString = "";
			for (int i = 0; i < OutBytes.Length; i++)
			{
				OutString += OutBytes[i].ToString("x2");
			}
			return OutString.ToUpper();

		}

		public UserEntity GetUserEntity(string userName)
		{
			ISession session = GetSession();
			UserEntity user = session.CreateCriteria<UserEntity>()
				.Add(Expression.Eq("UserName", userName))
				.UniqueResult<UserEntity>();
			return user;
		}

		public bool ReSendValidateMail(string email, string userId, string newEmail)
		{
			ISession session = GetSession();
			ITransaction tran = session.Transaction;
			tran.Begin();
			UserEntity user = session.CreateCriteria<UserEntity>()
				.Add(Expression.Eq("Id", userId))
				.Add(Expression.Eq("Email", email))
				.UniqueResult<UserEntity>();
			if (user == null)
				return false;
			user.Email = newEmail;

			session.Update(user);
			RegValidateEntity regVal = AddValidateEntity(user.Id, session);
			tran.Commit();
			SendValidateMail(user, regVal);
			return true;
		}

		public bool ValidateUser(RegValidateEntity regVal,ref object rtnObj)
		{
			ISession sess = GetSession();
			RegValidateEntity obj = sess.CreateCriteria<RegValidateEntity>()
				.Add(Expression.Eq("Id", regVal.Id))
				.Add(Expression.Eq("UserID", regVal.UserID))
				.Add(Expression.Eq("ValidateCode", regVal.ValidateCode))
				.UniqueResult<RegValidateEntity>();
			if (obj != null)
			{
				if (obj.IsUsed)
				{
					rtnObj = Resource.GetResource("Validate_CodeIsUsed"); ;
					return false;
				}
				ITransaction tran = sess.Transaction;
				tran.Begin();
				UserEntity user = sess.Get<UserEntity>(regVal.UserID);
				user.UserStatus = Common.Enums.UserStatus.Normal;
				sess.Update(user);
				obj.IsUsed = true;
				sess.Update(obj);
				tran.Commit();
				return true;
			}
			else
			{
				rtnObj =Resource.GetResource("Validate_Error") ;
				return false;
			}
		}

		public UserAttachEntity GetUserAttach(string userId)
		{
			ISession sess = GetSession();
			UserAttachEntity obj = sess.CreateCriteria<UserAttachEntity>()
				.Add(Expression.Eq("UserID", userId))
				.UniqueResult<UserAttachEntity>();
			return obj;
		}
	}
}
